package com.primeton.eos.bizlet.lucene;

import java.io.File;
import java.util.Date;

import net.paoding.analysis.analyzer.PaodingAnalyzer;
import net.paoding.analysis.knife.PaodingMaker;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.primeton.fbsearch.IndexFiles;
import com.primeton.tp.common.xml.XmlUtil;
import com.primeton.tp.core.api.BizContext;
/**
 * @author Administrator
 * @version 1.0
 * @date 2008-4-5
 * @class_displayName LuceneClient
 */

public class LuceneClient {

	
	
	/**
	 * 
	 * @param doc  type: Document, DOM;
	 * @param param type: BizContext;
	 * @return: int ,运算逻辑返回值，如果失败返回0，成功返回1
	 * @throws Exception    <p> ** bizlet 的显示名称 **
	 * @bizlet_displayName 文件全文搜索 
	 * @bizlet_param passing="in" type="EOSEntity" value="/" name=""  desc="Lucene搜索配置信息,支持分页返回搜索结果"

	 */
	public static int BL_SearchFiles(Document doc, BizContext param)
		throws Exception {


 
        String indexName = "";       //local copy of the configuration variable
        String startVal    = "";              //string version of startindex
        String maxresults  = "";              //string version of maxpage
        String queryString = "";             //the query entered in the previous page
 
          int startindex = 0;                     //the first index displayed on this page
          int maxpage    = 50;                    //the maximum items displayed on this page
          int thispage = 0;                       //used for the for/next either maxpage or
                                                  //hits.length() - startindex - whichever is
                                                  //less		

          
		Node node0 = (Node) param.getParaObjectAt(0);
		
		
		NodeList list = node0.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);
			if (node.getNodeName().equals("INDEX_HOME")) {
				indexName = node.getFirstChild().getNodeValue();
			} else if (node.getNodeName().equals("START_VAL")) {
				startVal = node.getFirstChild().getNodeValue();
			} else if (node.getNodeName().equals("MAX_RESULTS")) {
				maxresults = node.getFirstChild().getNodeValue();
			} else if (node.getNodeName().equals("QUERY_STRING")) {
				queryString = node.getFirstChild().getNodeValue();
			}
		}		
		
		 System.out.println(indexName+","+queryString);        
		          
 
       IndexSearcher searcher = null;          //the searcher used to open/search the index
        Query query = null;                     //the Query created by the QueryParser
        Hits hits = null;                       //the search results
         
        
          maxpage    = Integer.parseInt(maxresults);    //parse the max results first
          startindex = Integer.parseInt(startVal);      //then the start index       

     
          searcher = new IndexSearcher(indexName);  
       
//        Analyzer analyzer = new StandardAnalyzer();
        

       
 	 Analyzer analyzer = new org.apache.lucene.analysis.cjk.CJKAnalyzer();
    	   	
        QueryParser qp = new QueryParser("body", analyzer);
        

        query = qp.parse(queryString); //parse the 
        thispage = maxpage;    
        hits = searcher.search(query);                        // run the query 
        System.out.println("size="+hits.length());

        if ((startindex + maxpage) > hits.length()) {
            thispage = hits.length() - startindex;      // set the max index to maxpage or last
        }                
 
        
        Node node3 =XmlUtil.findNode(doc,"root/data/list[@type='SEARCH_FILES']");
        for (int i = startindex-1; i < (thispage + startindex); i++) {  // for each element
        	
            org.apache.lucene.document.Document doc1 = hits.doc(i);                    
            String name = doc1.get("name");            
            String path = doc1.get("path");                
             if ((name == null) || name.equals("")){ 
                    name = path;
                    
            }
             String modified = doc1.get("modified");
             String body = doc1.get("body");
             if(body!=null && body.length()>200){
            	 
            	 body = body.substring(100,200);
            	 
            	 //过滤非法xml字符
            	 StringBuffer stb = new StringBuffer();
            	 for(int j=0;j<body.length();j++){
            		 int c = body.charAt(j);
            		 if(isXMLCharacter(c)){            			 
            			 stb.append(c);
            		 }         		             		 
            	 }
            	 body = stb.toString();
             }
                                                          
            System.out.println("name"+","+name);  
 
            
        	Node tmpdoc = (Node) doc.createElement("Document");
        	((Element)tmpdoc).setAttribute("rowNum", Integer.toString(i));
			
        	Node tmpname = (Node) doc.createElement("name");	 
			XmlUtil.setNodeValue(tmpname, name);
			
        	Node tmppath= (Node) doc.createElement("path");	 
			XmlUtil.setNodeValue(tmppath, path);
			
        	Node tmpmod= (Node) doc.createElement("modified");	 
			XmlUtil.setNodeValue(tmpmod, modified);
			
        	Node tmpbody= (Node) doc.createElement("body");	 
			XmlUtil.setNodeValue(tmpbody, body);				
					
			tmpdoc.appendChild(tmpname);
			tmpdoc.appendChild(tmppath);
			tmpdoc.appendChild(tmpmod);
			tmpdoc.appendChild(tmpbody);
			
			
			
			
			 node3.appendChild( tmpdoc);			
			
            
        }   
        Node tmpcount= (Node) doc.createElement("count");	 
		XmlUtil.setNodeValue(tmpcount, String.valueOf(hits.length()));		

        
        node3.appendChild( tmpcount);	
  

		return 1;
	}

	/**
	 * 
	 * @param doc  type: Document, DOM;
	 * @param param type: BizContext;
	 * @return: int ,运算逻辑返回值，如果失败返回0，成功返回1
	 * @throws Exception    <p> ** bizlet 的显示名称 **
	 * @bizlet_displayName 建立索引 
	 * @bizlet_param passing="in" type="EOSEntity" value="/" name=""  desc="Lucene建立索引配置信息"
	 */
	public static int BL_IndexFiles(Document doc, BizContext param) throws Exception {
		
        String indexHome = "";        
        String dataHome    = "";             
 

		Node node0 = (Node) param.getParaObjectAt(0);
	 
		
		NodeList list = node0.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);
			if (node.getNodeName().equals("INDEX_HOME")) {
				indexHome = node.getFirstChild().getNodeValue();
			} else if (node.getNodeName().equals("DATA_HOME")) {
				dataHome = node.getFirstChild().getNodeValue();
			}  
		}	
 

	    Directory dir = FSDirectory.getDirectory(indexHome,true);
	   
	    
//	     Analyzer analyzer = new StandardAnalyzer();
		 Analyzer analyzer = new org.apache.lucene.analysis.cjk.CJKAnalyzer();
	    
	    IndexWriter writer = new IndexWriter(dir, analyzer, true);

	    IndexFiles indexer = new IndexFiles();

	    long start = new Date().getTime();
	    indexer.index(writer, new File(dataHome));
	    writer.optimize();
	    writer.close();
	    long end = new Date().getTime();

	    System.out.println();
	    IndexReader reader = IndexReader.open(dir);
	    System.out.println("Documents indexed: " + reader.numDocs());
	    System.out.println("Total time: " + (end - start) + " ms");
	    reader.close();		
		
		return 1;
	}
	
	   private static boolean isXMLCharacter(int c) {

	         if (c <= 0xD7FF)  {

	             if (c >= 0x20) return true;

	             else {

	                  if (c == '\n') return true;

	                  if (c == '\r') return true;

	                  if (c == '\t') return true;

	                  return false;

	             }

	         }

	 

	         if (c < 0xE000) return false;  if (c <= 0xFFFD) return true;

	         if (c < 0x10000) return false;  if (c <= 0x10FFFF) return true;

	       

	         return false;

	    }

	

}
